﻿using HDS.IService.Master;
using HDS.Model.Entity.Master;
using LinqKit;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using HDS.Common.Helper;
using HDS.Model;
using SqlSugar;
using Newtonsoft.Json;
using HDS.IService.Log;
using HDS.Model.Entity.Log;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
using HDS.Admin.Api.ViewModels.Hotel;

namespace HDS.Admin.Api.Controllers
{
    [Route("hotel/[action]")]
    [ApiController]
    [EnableCors]
    [Authorize]
    public class HotelController : AdminController
    {
        private readonly ILogger<HotelController> _logger;
        private readonly IHotelService _IHotelService;
        private readonly ISupplierHotelService _ISupplierHotelService;
        private readonly ISupplierApiConfigService _ISupplierApiConfigService;
        private readonly IDistributorService _IDistributorService;
        private readonly IUpdateLogService _IUpdateLogService;
        private readonly IMappingService _IMappingService;

        public HotelController(ILogger<HotelController> logger, IHotelService ihotelService, ISupplierHotelService isupplierHotelService, ISupplierApiConfigService isupplierApiConfigService, IDistributorService idistributorConfigService, IUpdateLogService iupdateLogService, IMappingService imappingService)
        {
            _logger = logger;
            _IHotelService = ihotelService;
            _ISupplierHotelService = isupplierHotelService;
            _ISupplierApiConfigService = isupplierApiConfigService;
            _IDistributorService = idistributorConfigService;
            _IUpdateLogService = iupdateLogService;
            _IMappingService = imappingService;
        }

        public async Task<ResultData<DataPagingModel<Hotel>>> GetHotelList([FromBody] SearchDto searchDto)
        {
            var hotelNameEn = (searchDto.HotelName ?? "").IsEnglish() ? searchDto.HotelName : "";
            var hotelNameCn = (searchDto.HotelName ?? "").IsEnglish() ? "" : searchDto.HotelName;

            var predicate = PredicateBuilder.New<Hotel>(e => e.HotelStatus);
            var whereSql = "";
            if (searchDto.HotelId.HasValue)
                predicate = predicate.And(e => e.HotelId == searchDto.HotelId);
            if (searchDto.HotelStar.HasValue)
                predicate = predicate.And(e => e.HotelStar == searchDto.HotelStar);
            if (!string.IsNullOrEmpty(hotelNameEn))
            {
                var name = "+" + hotelNameEn.Trim().RemoveNotLetterNumber().ReplaceMultSpaceToOne().Replace(" ", " +");
                whereSql = "MATCH(hotel_name_en) AGAINST('" + name.Trim().FilterSql() + "' IN BOOLEAN MODE)";
            }
            if (!string.IsNullOrEmpty(hotelNameCn))
                predicate = predicate.And(e => e.HotelNameCn.Contains(hotelNameCn.Trim()));
            if (!string.IsNullOrEmpty(searchDto.CountryName))
                predicate = predicate.And(e => e.CountryName.Contains(searchDto.CountryName.Trim()));
            if (!string.IsNullOrEmpty(searchDto.CityName))
                predicate = predicate.And(e => e.CityName.Contains(searchDto.CityName.Trim()));
            if (!string.IsNullOrEmpty(searchDto.Distributor))
                whereSql = (string.IsNullOrEmpty(whereSql) ? "" : whereSql + " AND ") + $"hotel_id NOT IN (select d.hotel_id from `distributor_hotel` d where d.distributor = '{searchDto.Distributor.ToSqlFilter()}')";

            var dataPaging = await _IHotelService.GetHotelList(searchDto.PageIndex, searchDto.PageSize, predicate, whereSql);

            return new ResultData<DataPagingModel<Hotel>> { Success = true, Data = dataPaging };
        }

        public async Task<ResultData<Hotel>> GetHotel(int hotelId)
        {
            var hotelInfo = await _IHotelService.GetHotel(hotelId);

            return new ResultData<Hotel> { Success = true, Data = hotelInfo };
        }

        public async Task<ResultData<int>> UpdateHotel(Hotel entity)
        {
            UpdateLog updateLog = null;
            if (entity.HotelId > 0)
            {
                var hotel = await _IHotelService.GetHotel(entity.HotelId);
                updateLog = new UpdateLog
                {
                    LogType = UpdateLogType.StaticData,
                    LogSubType = "UpdateHotel",
                    LogText = $"Update Hotel {entity.HotelId}, 原数据 {JsonConvert.SerializeObject(hotel)}",
                    BusinessId = entity.HotelId.ToString(),
                    UpdatedBy = this.UserId,
                    UpdatedByName = this.UserName,
                    UpdatedTime = DateTime.Now
                };
            }

            entity.UpdatedBy = this.UserId;
            entity.UpdatedByName = this.UserName;
            entity.UpdatedTime = DateTime.Now;
            var hotelId = await _IHotelService.UpdateHotel(entity);

            if (updateLog == null)
            {
                updateLog = new UpdateLog
                {
                    LogType = UpdateLogType.StaticData,
                    LogSubType = "UpdateHotel",
                    LogText = $"Add Hotel {hotelId}, 数据 {JsonConvert.SerializeObject(entity)}",
                    BusinessId = hotelId.ToString(),
                    UpdatedBy = this.UserId,
                    UpdatedByName = this.UserName,
                    UpdatedTime = DateTime.Now
                };
            }
            await _IUpdateLogService.Add(updateLog);

            return new ResultData<int> { Success = true, Data = hotelId };
        }

        public async Task<ResultData<int>> DeleteHotel(int hotelId)
        {
            await _IHotelService.DeleteHotel(hotelId);
            return new ResultData<int> { Success = true };
        }

        public async Task<ResultData<object>> GetRoomList(int hotelId)
        {
            var list = await _IHotelService.GetRoomList(hotelId);

            return new ResultData<object>
            {
                Success = true,
                Data = new
                {
                    RoomList = list.OrderByDescending(e => e.RoomStatus).ThenByDescending(e => e.RoomId),
                    DefaultBeds = RoomBedType.GetDefaultBeds()
                }
            };
        }

        public async Task<ResultData<int>> UpdateRoom(HotelRoom entity)
        {
            UpdateLog updateLog = null;
            if (entity.RoomId > 0)
            {
                var room = await _IHotelService.GetRoom(entity.RoomId);
                updateLog = new UpdateLog
                {
                    LogType = UpdateLogType.StaticData,
                    LogSubType = "UpdateRoom",
                    LogText = $"Update Room {entity.RoomId}, 原数据 {JsonConvert.SerializeObject(room)}",
                    BusinessId = entity.HotelId.ToString(),
                    UpdatedBy = this.UserId,
                    UpdatedByName = this.UserName,
                    UpdatedTime = DateTime.Now
                };
            }

            entity.UpdatedBy = this.UserId;
            entity.UpdatedByName = this.UserName;
            entity.UpdatedTime = DateTime.Now;
            entity.RoomId = await _IHotelService.UpdateRoom(entity);

            if (updateLog == null)
            {
                updateLog = new UpdateLog
                {
                    LogType = UpdateLogType.StaticData,
                    LogSubType = "UpdateRoom",
                    LogText = $"Add Room {entity.RoomId}, 数据 {JsonConvert.SerializeObject(entity)}",
                    BusinessId = entity.HotelId.ToString(),
                    UpdatedBy = this.UserId,
                    UpdatedByName = this.UserName,
                    UpdatedTime = DateTime.Now
                };
            }
            await _IUpdateLogService.Add(updateLog);

            return new ResultData<int> { Success = true };
        }

        public async Task<ResultData<int>> DeleteRooms([FromBody] int[] roomIds)
        {
            foreach (var roomId in roomIds)
            {
                var room = await _IHotelService.GetRoom(roomId);
                if (room != null && room.RoomStatus)
                {
                    await _IHotelService.DeleteRoom(roomId);
                    await _IUpdateLogService.Add(new UpdateLog
                    {
                        LogType = UpdateLogType.StaticData,
                        LogSubType = "DeleteRoom",
                        LogText = $"Delete Room {roomId}",
                        BusinessId = room.HotelId.ToString(),
                        UpdatedBy = this.UserId,
                        UpdatedByName = this.UserName,
                        UpdatedTime = DateTime.Now
                    });
                }
            }
            return new ResultData<int> { Success = true };
        }

        public async Task<ResultData<int>> RestoreRooms([FromBody] int[] roomIds)
        {
            foreach (var roomId in roomIds)
            {
                var room = await _IHotelService.GetRoom(roomId);
                if (room != null && !room.RoomStatus)
                {
                    await _IHotelService.RestoreRoom(roomId);
                    await _IUpdateLogService.Add(new UpdateLog
                    {
                        LogType = UpdateLogType.StaticData,
                        LogSubType = "RestoreRoom",
                        LogText = $"Restore Room {roomId}",
                        BusinessId = room.HotelId.ToString(),
                        UpdatedBy = this.UserId,
                        UpdatedByName = this.UserName,
                        UpdatedTime = DateTime.Now
                    });
                }
            }
            return new ResultData<int> { Success = true };
        }

    }
}
